home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Unix / gopher+1.2b4 / gopherd / authenticate.c next >
Encoding:
C/C++ Source or Header  |  1993-04-09  |  15.4 KB  |  595 lines

  1. /********************************************************************
  2.  * lindner
  3.  * 3.5
  4.  * 1993/04/10 06:07:17
  5.  * /home/mudhoney/GopherSrc/CVS/gopher+/gopherd/authenticate.c,v
  6.  * Exp
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992, 1993 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: authenticate.c
  14.  * Routines to do encryption and decryption, and validate tickets
  15.  *********************************************************************
  16.  * Revision History:
  17.  * authenticate.c,v
  18.  * Revision 3.5  1993/04/10  06:07:17  lindner
  19.  * none
  20.  *
  21.  * Revision 3.4  1993/04/09  16:51:54  lindner
  22.  * Little mods for combined public gopher and admit1 gopher.
  23.  *
  24.  * Revision 3.3  1993/04/07  05:16:57  lindner
  25.  * Unhid changes for Admit1 stuff.
  26.  *
  27.  * Revision 3.1  1993/03/19  20:02:13  lindner
  28.  * DES and ticket routines
  29.  *
  30.  *
  31.  *********************************************************************/
  32.  
  33.  
  34.  
  35. /* -------------------------------------------------
  36.  *
  37.  * Sofware DES functions 12 Dec 1986 by Phil Karn, KA9Q;
  38.  * large sections from 1977 public-domain program by Jim Gillogly
  39.  * Modified by George Gonzalez to not do initial/final permutations
  40.  * Further bludgeoned by Farhad Anklesaria for AdmitOne authentication.
  41.  *
  42.  ---------------------------------------------------- */
  43.  
  44. #define  SLEN 255  /* Generic small buffer length */
  45. extern int DEBUG;
  46.  
  47. static int IntelOrder;     /*Hacked out.  fxa*/
  48.  
  49. /* Tables defined in the Data Encryption Standard documents */
  50. /* permuted choice table (key) */
  51. static char pc1[] = {
  52.      57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
  53.      10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
  54.      
  55.      63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
  56.      14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
  57.      };
  58.  
  59. /* number left rotations of pc1 */
  60. static char totrot[] = { 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
  61.  
  62. /* permuted choice key (table) */
  63. static char pc2[] = {
  64.      14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
  65.      23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
  66.      41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
  67.      44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
  68.      };
  69.  
  70. /* The (in)famous S-boxes */
  71. static char si[8][64] = {
  72.      /* S1 */
  73.      14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
  74.      0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
  75.      4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
  76.      15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
  77.      
  78.      /* S2 */
  79.      15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
  80.      3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
  81.      0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
  82.      13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
  83.      
  84.      /* S3 */
  85.      10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
  86.      13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
  87.      13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
  88.      1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
  89.      
  90.      /* S4 */
  91.      7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
  92.      13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
  93.      10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
  94.      3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
  95.      
  96.      /* S5 */
  97.      2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
  98.      14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
  99.      4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
  100.      11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
  101.      
  102.      /* S6 */
  103.      12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
  104.      10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
  105.      9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
  106.      4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
  107.      
  108.      /* S7 */
  109.      4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
  110.      13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
  111.      1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
  112.      6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
  113.      
  114.      /* S8 */
  115.      13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
  116.      1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
  117.      7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
  118.      2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
  119.      };
  120.  
  121. /* 32-bit permutation  P used on the output of the S-boxes */
  122. static char p32i[] = { 
  123.      16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
  124.      2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
  125.      };
  126.  
  127. /* Lookup tables initialized once only at startup by desinit() */
  128.  
  129.  
  130.   
  131. /* bit 0 == left-most in byte */
  132. static short bytebit[] = { 0200,0100,0040,0020,0010,0004,0002,0001 };
  133.   
  134.   
  135. char ticket[SLEN] = "3135323020202020";  /* 1520 */
  136. char pw[SLEN] =     "61646D6974312020";  /* admit1 */
  137. char pt[SLEN] = "1520    ";  /* 1520 */
  138. char pt2[SLEN]; 
  139. unsigned long tNum;
  140.  
  141. static unsigned char (*kn)[8];
  142. static int (*spbox)[64]; /* Combined S && P boxes */
  143.   
  144. /*-------------MAIN--------------*/
  145. #ifdef ADMIT1TEST
  146.  
  147. int DEBUG = 1;
  148. Abort()
  149. {
  150.      exit(-1);
  151. }
  152.  
  153. main(argc, argv)
  154.   int argc;
  155.   char * argv[];
  156. {
  157.      unsigned long out[3];
  158.      
  159.      printf("ick.  here we go.\n");
  160.      tNum = atoi(pt);
  161.      printf("tNum converted from string: %d\n", tNum);
  162.      sprintf(pt2, "%X%X%X%X%X%X%X%X", pt[0],pt[1],pt[2],pt[3],pt[4],pt[5],pt[6],pt[7] );
  163.      printf("pt2 converted to hex from str: %s\n", pt2);
  164.      printf("Ticket: %s\n", ticket);
  165.      printf("pw: %s\n", pw);
  166.      encrypt(ticket, pw, out );
  167.      sprintf(ticket, "%.8lX%.8lX", out[0], out[1]);
  168.      printf("converted to string: %s\n", ticket);
  169.      decrypt(ticket, pw, out);
  170.      
  171.      decrypt("374506700551A6B6", pw, out);
  172.      
  173.      if ( desinit() == 0 ) desdone();
  174. }
  175.  
  176. #endif
  177.  
  178. /*--------------------------------*/
  179. /* Initialize the lookup table for the combined S && P boxes */
  180. void spinit()
  181. {
  182.      char pbox[ 32 ];
  183.      short p, i, s, j, t, rowcol;
  184.      int val;
  185.      
  186.      for ( p = 1; p <= 32; p++ ) {
  187.       for ( i = 0; i <= 31; i++ ) {
  188.            if ( p32i[ i ] == p ) {
  189.             pbox[ p - 1 ] = 31 - i;
  190.             break;
  191.            }
  192.       }
  193.      }
  194.      for ( s = 0; s <= 7; s++ ) {
  195.       for ( i = 0; i <= 63; i++ ) {
  196.            val = 0;
  197.            rowcol = (i & 32) | ((i & 1) ? 16 : 0) | ((i >> 1) & 0xf);
  198.            t = si[ s ] [ rowcol ];
  199.            for ( j = 0; j <= 3; j++ ) {
  200.             if ( t & ( 8 >> j ) ) {
  201.              val |= 1L << pbox[ ( s << 2 ) + j ];
  202.             }
  203.            }
  204.            spbox[ s ] [ i ] = val;
  205.       }
  206.      }
  207. }
  208.  
  209.  
  210. /*--------------------------------*/
  211. /* Allocate space && initialize DES lookup arrays
  212.  * mode == 1: DEA without initial && final permutations for speed
  213.  */
  214.  
  215. desinit()
  216. {
  217.      if ( spbox != 0 ) return 0; 
  218.      
  219.      spbox = ( int (*)[64] ) malloc( sizeof( int ) * 8 * 64);
  220.      if ( spbox != 0) { 
  221.       spinit();
  222.       kn = (unsigned char (*)[8]) malloc( sizeof( char ) * 8 * 16);
  223.       if ( kn == 0 ) {
  224.            free( (char *) spbox );
  225.            spbox = 0;
  226.       } 
  227.      }
  228.      if ( spbox == 0 || kn == 0 ) {
  229.       return -1;
  230.      } else {
  231.       return 0;
  232.      }
  233. }
  234.  
  235. /*--------------------------------*/
  236. /* Free up storage used by DES */
  237.  
  238. desdone()
  239.      if (spbox != 0) {
  240.       free( (char *) spbox );
  241.       free( (char *) kn );
  242.       spbox = 0;
  243.       kn = 0;
  244.      }
  245. }
  246.  
  247.  
  248. /*--------------------------------*/
  249.  
  250. void setdeskey( key ) char * key;
  251. {
  252.      char pc1m[56];  /* place to modify pc1 into */
  253.      char pcr[56];  /* place to rotate pc1 into */
  254.      register short i, j, k;
  255.      
  256.      /* Clear key schedule */
  257.      for (i=0; i<16; i++) {
  258.       for (j=0; j<8; j++) {
  259.            kn[i][j]=0;
  260.       }
  261.      }
  262.      
  263.      for (j=0; j<56; j++) {  /* convert pc1 to bits of key */
  264.       k = pc1[ j ] - 1;
  265.       pc1m[ j ] = ( key[ k >> 3 ]  & bytebit[ k & 07 ]) ? 1 : 0;
  266.      } 
  267.      
  268.      for (i=0; i<16; i++) {  /* key chunk for each iteration */
  269.       for (j=0; j<56; j++) { /* rotate pc1 the right amount */
  270.            k = j + totrot[ i ];
  271.            pcr[ j ] = pc1m[ k < ( j < 28 ? 28 : 56 ) ? k : k - 28 ];
  272.       }
  273.       for (j=0; j<48; j++) { /* select bits individually */
  274.            if ( pcr[ pc2[ j ] - 1 ] ) {
  275.             kn[ i ] [ j / 6 ] |= bytebit[ j % 6 ] >> 2;
  276.            }
  277.       }
  278.      }
  279. }
  280.  
  281.  
  282. /*--------------------------------*/
  283.  
  284. void byteswap( x ) 
  285.   unsigned long * x;
  286. {
  287.      register char * cp;
  288.      register char tmp;
  289.      
  290.      cp = (char *) x;
  291.      tmp = cp[3];
  292.      cp[3] = cp[0];
  293.      cp[0] = tmp;
  294.      
  295.      tmp = cp[2];
  296.      cp[2] = cp[1];
  297.      cp[1] = tmp;
  298. }
  299.  
  300.  
  301. /*--------------------------------*/
  302.  
  303. void mv( in, out ) char * in, *out;
  304. {  short i;
  305.    
  306.    for ( i = 0; i <= 7; i++ ) out[i] = in[i];
  307.    if ( IntelOrder ) {
  308.     byteswap( (unsigned long * ) &out[0] );
  309.     byteswap( (unsigned long * ) &out[4] );
  310.    }
  311. }
  312.  
  313.  
  314. /*--------------------------------*/
  315. /* The nonlinear  f(r,k), the heart of DES */
  316.  
  317. int f( r, subkey ) unsigned long r; unsigned char subkey[8];
  318. {
  319.      register unsigned long rval, rt;
  320.      
  321.      /* Run E(R) ^ K through the combined S & P boxes
  322.       * This ; takes advantage of a convenient regularity in
  323.       * E, namely that each group of 6 bits in E(R) feeding
  324.       * a single S-box == a contiguous segment of R.
  325.       */
  326.      rt = (r >> 1) | ((r & 1) ? 0x80000000 : 0);
  327.      rval = 0;
  328.      rval |= spbox[0][((rt >> 26) ^ *subkey++) & 0x3f];
  329.      rval |= spbox[1][((rt >> 22) ^ *subkey++) & 0x3f];
  330.      rval |= spbox[2][((rt >> 18) ^ *subkey++) & 0x3f];
  331.      rval |= spbox[3][((rt >> 14) ^ *subkey++) & 0x3f];
  332.      rval |= spbox[4][((rt >> 10) ^ *subkey++) & 0x3f];
  333.      rval |= spbox[5][((rt >> 6) ^ *subkey++) & 0x3f];
  334.      rval |= spbox[6][((rt >> 2) ^ *subkey++) & 0x3f];
  335.      rt = (r << 1) | ((r & 0x80000000) ? 1 : 0);
  336.      rval |= spbox[7][(rt ^ *subkey) & 0x3f];
  337.      return rval;
  338. }
  339.  
  340. /*--------------------------------*/
  341.  
  342. void pass( num, block ) short num; unsigned long *block;
  343. {
  344.      short b;
  345.      
  346.      b = num & 1;
  347.      block[ b ] ^= f( block[ 1 - b ], kn[ num ] );
  348. }
  349.  
  350.  
  351.  
  352.  
  353. /*--------------------------------*/
  354. /* In-place encryption of 64-bit block */
  355.  
  356. void endes(block) 
  357.   unsigned long * block;
  358. {
  359.      register short i;
  360.      unsigned long work[3];   /* Working data storage */
  361.      int tmp;
  362.      
  363.      mv( ( char * ) block, (char * ) work ); /* Initial Permutation */
  364.      for (i=0; i<16; i++)
  365.       pass( i, work );
  366.      tmp = work[0];
  367.      work[0] = work[1]; 
  368.      work[1] = tmp;
  369.      mv( (char *) work, (char *) block );
  370. }
  371.  
  372.  
  373.  
  374. /*--------------------------------*/
  375. /* In-place decryption of 64-bit block */
  376. void dedes(block) 
  377.   unsigned long * block;
  378. {
  379.      register short i;
  380.      unsigned long work[3]; /* Working data storage */
  381.      int tmp;
  382.      ;
  383.      mv( (char * ) block, (char *) work ); /* Initial permutation */
  384.      
  385.      /* Left/right half swap */
  386.      tmp = work[0];
  387.      work[0] = work[1]; 
  388.      work[1] = tmp;
  389.      
  390.      /* Do the 16 rounds in reverse order */
  391.      for ( i = 0; i <=15; i++ )
  392.       pass( 15 - i, work );
  393.      
  394.      mv( (char *)work, (char *) block );
  395. }
  396.  
  397. /*--------------------------------*/
  398.  
  399. short  Hx( c ) 
  400.   char c;
  401. {
  402.      if ( c >= '0' && c <= '9' ) {
  403.       return( c - '0' );
  404.      } else {
  405.       if ( c >= 'A' && c <= 'F' )
  406.            return( c - 'A' + 10 );
  407.       else if ( c >= 'a' && c <= 'f' )
  408.            return( c - 'a' + 10);
  409.       else
  410.            return( 0 );
  411.      }
  412. }
  413.  
  414.  
  415. /*--------------------------------*/
  416. /* Take a character string and convert it into two long ints 
  417. */
  418.  
  419. void HexToBin( In, Out ) 
  420.   char * In; 
  421.   unsigned long Out[];
  422. {
  423.      short i;
  424.      char * OutC;
  425.      int bytes[8];
  426.  
  427.  
  428.      for (i=0; i < 8; i++) 
  429.       bytes[i] = (Hx(In[i*2]) * 16 ) + Hx(In[i*2 + 1]);
  430.  
  431.      Out[0] = (bytes[0]*16777216) + (bytes[1]*65536) + (bytes[2]*256) + bytes[3];
  432.  
  433.      Out[1] = (bytes[4]*16777216) + (bytes[5]*65536) + (bytes[6]*256) + bytes[7];
  434.  
  435.      if (DEBUG)
  436.       printf("Output of HextoBin is %X%X\n", Out[0], Out[1]);
  437. }
  438.  
  439.  
  440. /*--------------------------------*/
  441.  
  442. decrypt( pwrd, key, out ) 
  443.   char * pwrd; 
  444.   char * key; 
  445.   unsigned long out[];
  446. {
  447.      short i;
  448.      unsigned long bpwrd[3], bkey[3];
  449.      char * OutC;
  450.      
  451.      if ( desinit() != 0 ) Abort("DES could ! init itself.\n");
  452.      
  453.      HexToBin( pwrd, bpwrd );
  454.      HexToBin( key, bkey );
  455.      setdeskey( ( char * ) bkey );
  456.      for ( i = 0; i <= 1; i++ )
  457.       out[ i ] = bpwrd[ i ];
  458.      dedes( out );
  459.      OutC = (char *) out;
  460.      OutC[ 8 ] = '\0';
  461.      if (DEBUG) {
  462.       printf("decrypt: key = %.8lX%.8lX\n", bkey[0], bkey[1] );
  463.       printf("input: %.8lX%.8lX, output = %.8lX%.8lX  '%s'\n",
  464.          bpwrd[0], bpwrd[1], out[0], out[1],(char *) out);
  465.      }
  466. }
  467.  
  468. /*--------------------------------*/
  469.  
  470. encrypt( pwrd, key, out )
  471.   char * pwrd; 
  472.   char * key; 
  473.   unsigned long out[];
  474. {
  475.      short i;
  476.      unsigned long bpwrd[3], bkey[3];
  477.      
  478.      if ( desinit() != 0 ) Abort("Error initializing DES.\n");
  479.      HexToBin( pwrd, bpwrd );
  480.      HexToBin( key, bkey );
  481.      setdeskey( (char *) bkey );
  482.      for ( i = 0; i <=1; i++ )
  483.       out[ i ] = bpwrd[ i ];
  484.      endes( out );
  485.      if (DEBUG) {
  486.       printf("encrypt: key = %.8lX%.8lX\n", bkey[0], bkey[1] );
  487.       printf("input: %.8lX%.8lX, output = %.8lX%.8lX\n",
  488.          bpwrd[0], bpwrd[1], out[0], out[1]);
  489.      }
  490. }
  491.  
  492.  
  493. #include "String.h"
  494. #include <stdio.h>
  495. #include <sys/types.h>
  496.  
  497. #include "gopherd.h"
  498. #include "tix.h"
  499. #include "command.h"
  500.  
  501. /*--------------------------------*/
  502. /** Test for a ticket 
  503.     Find out if the request has a ticket,
  504.  
  505.     If not, print out an error message on sockfd and exit 
  506. **/
  507.  
  508. PleaseAuthenticate(sockfd, string)
  509.   int  sockfd;
  510.   char *string;
  511. {
  512.      /*** Should be "gplus error...  oh well... ****/
  513.      
  514.      writestring(sockfd, "--2\r\n4 *UMNDES based auth required\r\nServer Requires Authenication\r\n");
  515.       closenet(sockfd);
  516.      return(0);
  517. }
  518.  
  519. TixObj *
  520. ValidTicket(sockfd, cmd)
  521.   int sockfd;
  522.   CMDobj *cmd;
  523. {
  524.      int fd;
  525.      TixArray *Tickets;
  526.      char *cp;
  527.      TixObj *tix, *ReturnTix;
  528.  
  529.      
  530.      Tickets = TIXAnew();
  531.      
  532.      fd = uopen(GDCgetTixfile(Config), O_RDWR, 0644);
  533.      TIXAfromFile(Tickets, fd);
  534.      
  535.      if (CMDgetCommand(cmd) != NULL && strcmp(CMDgetCommand(cmd), "!+TIX")==0) {
  536.       int i;
  537.       char outputline[512];
  538.       
  539.       
  540.       i = TIXAsearchUser(Tickets, CMDgetUser(cmd));
  541.       tix = TIXAgetEntry(Tickets, i);
  542.       
  543.       if (i <0) {
  544.            GplusError(sockfd, 1, "Sorry, you don't have an account...", NULL);
  545.            return(NULL);
  546.       }
  547.       
  548.       TIXrandomTicket(TIXAgetEntry(Tickets, i));
  549.       cp = TIXgetCryptedTicket(TIXAgetEntry(Tickets, i));
  550.  
  551.       sprintf(outputline, "+-1\r\n+INFO: 1%s\t\t%s\t%d\r\n+TIX: %s\r\n.\r\n", GDCgetSite(Config), GDCgetHostname(Config), GDCgetPort(Config), cp);
  552.       
  553.       writestring(sockfd, outputline);
  554.       TIXusedTicket(tix);
  555.       lseek(fd, 0 , SEEK_SET);
  556.       TIXAtoFile(Tickets, fd);
  557.       
  558.       TIXAdestroy(Tickets);
  559.       return(NULL);
  560.      } else {
  561.       /*** Validate the request ***/
  562.       int i;
  563.       
  564.       if (TIXAvalid(Tickets, CMDgetUser(cmd), CMDgetTicket(cmd)) == FALSE) {
  565.            AccessDenied(sockfd);
  566.            return(NULL);
  567.       }
  568.       i = TIXAsearchUser(Tickets, CMDgetUser(cmd));
  569.       tix = TIXAgetEntry(Tickets, i);
  570.       TIXusedTicket(tix);
  571.  
  572.       if (DEBUG)
  573.            printf("Ticket user is %s\n", TIXgetUser(tix));
  574.       ReturnTix = TIXnew();
  575.       TIXcpy(ReturnTix, tix);
  576.       if (DEBUG)
  577.            printf("Ticket user is %s\n", TIXgetUser(tix));
  578.       
  579.       lseek(fd, 0 , SEEK_SET);
  580.       TIXAtoFile(Tickets, fd);
  581.       TIXAdestroy(Tickets);
  582.       return(ReturnTix);
  583.      }
  584. }
  585.  
  586.  
  587. AccessDenied(sockfd)
  588.   int sockfd;
  589. {
  590.      GplusError(sockfd, 5, "*UMNDES", NULL);
  591.      writestring(sockfd, "--2\r\n5 *UMNDES based auth required\r\nServer Requires Authentication\r\n");
  592.      return(NULL);
  593. }
  594.